package com.hjh.usb.accessory.communication

import com.elvishew.xlog.XLog
import kotlinx.coroutines.*
import java.io.File
import java.io.InputStream
import java.io.OutputStream
import java.util.concurrent.atomic.AtomicBoolean


class AOACommunicator(
    private val inputStreamProvider: () -> InputStream?,
    private val outputStreamProvider: () -> OutputStream?,
) {
    companion object {
        private const val BUFFER_SIZE = 32 * 1024
    }

    private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
    private var ackReceived = CompletableDeferred<Unit>()
    private val sending = AtomicBoolean(false)

    /**
     * 启动接收线程，监听 Ack 包
     */
    @OptIn(ExperimentalStdlibApi::class)
    fun start() {
        scope.launch {
            val buffer = ByteArray(BUFFER_SIZE)
            while (UsbFlow.usbConnState.value is ConnectionState.Connected && isActive) {
                try {
                    val bytesRead = inputStreamProvider()?.read(buffer) ?: -1
                    if (bytesRead > 0) {
                        val data = buffer.copyOf(bytesRead)
                        // XLog.tag("Accessory Receive").i(data.toHexString())
                        if (PacketUtils.isAckPacket(data) && sending.get()) {
                            ackReceived.complete(Unit)  // 唤醒发送者
                        }
                    }
                } catch (e: Exception) {
                    e.printStackTrace()
                    UsbFlow.updateConnectionState(
                        ConnectionState.Error("接收错误: ${e.message}")
                    )
                    break
                }
            }
        }
    }

    /**
     * 顺序发送文件，发送每包后等待 Ack 确认
     */
    fun sendFile(file: File): Boolean {
        if (UsbFlow.usbConnState.value !is ConnectionState.Connected) return false
        scope.launch {
            try {
                val fileSize = file.length()
                var chunkIndex = 0

                file.inputStream().use { fis ->
                    val buffer = ByteArray(BUFFER_SIZE)

                    while (true) {
                        val bytesRead = fis.read(buffer)
                        if (bytesRead <= 0) break

                        val packet = PacketUtils.buildDataPacket(
                            fileSize = fileSize,
                            chunkIndex = chunkIndex++,
                            data = buffer,
                            length = bytesRead
                        )

                        sending.set(true)
                        ackReceived = CompletableDeferred() // 每次都创建新的

                        try {
                            outputStreamProvider()?.write(packet)
                            outputStreamProvider()?.flush()
                            // XLog.tag("Accessory Send").i("Chunk $chunkIndex 发送完成，等待 Ack")
                        } catch (e: Exception) {
                            UsbFlow.updateConnectionState(ConnectionState.Error("发送错误: ${e.message}"))
                            return@launch
                        }

                        withTimeoutOrNull(60_000) {
                            ackReceived.await()
                        } ?: run {
                            UsbFlow.updateConnectionState(ConnectionState.Error("等待 Ack 超时"))
                            return@launch
                        }

                        sending.set(false)
                    }
                }

                XLog.tag("Accessory Send").i("文件发送完成")
            } catch (e: Exception) {
                e.printStackTrace()
                UsbFlow.updateConnectionState(ConnectionState.Error("文件发送异常: ${e.message}"))
            }
        }
        return true
    }

    // 停止通信，释放资源
    fun stop() {
        scope.cancel()  // 停止所有协程
        if (!ackReceived.isCompleted) {
            ackReceived.completeExceptionally(CancellationException("中止通信"))
        }

        sending.set(false)
        XLog.tag("Accessory").i("通信已停止，资源释放完毕")
    }
}
